﻿using Avalonia.Media;
using Project2004.Jigsaw.Utils;
using System;
using System.Text;

namespace Project2004.Jigsaw.Helpers
{
    public static class InsertDirectionHelper
    {
        public static InsertDirection Reverse(InsertDirection value)
        {
            if (value == InsertDirection.Left)
            {
                return InsertDirection.Right;
            }
            else if (value == InsertDirection.Right)
            {
                return InsertDirection.Left;
            }
            else if (value == InsertDirection.Up)
            {
                return InsertDirection.Down;
            }
            else if (value == InsertDirection.Down)
            {
                return InsertDirection.Up;
            }
            else
            {
                throw new NotImplementedException();
            }

        }

        public static HoleType Reverse(HoleType value)
        {
            if (value == HoleType.Flat) return HoleType.Flat;
            if (value == HoleType.In) return HoleType.Out;
            return HoleType.In;
        }

    }

    [Obsolete("完全过时的解决方案！", error: true)]
    public static class PathHelper
    {
        ///<summary>顺时针绘制。</summary>
        private static string GetCurve(InsertDirection direction, double size = 100d)
        {
            // 左边的朝向。
            var unitSize = 100d;
            var scale = size / unitSize;

            var sb = new StringBuilder();

            // 从下到上。
            double[] arr = [
                -0.2098, -2.3454, -1.5723, -4.8794, -3.5625, -6.0312,
                -2.1646, -1.2527 , -4.9854, -1.2418 ,-7.1562, 0 ,
                -6.2718 ,2.4209 , -12.598 ,6.2676 , -19.438 ,6.0312,
                -10.834, 0 , -19.708 ,-8.5193 , -20.25, -19.219,
                -0.017, -0.3451 , 0, -0.68175 , 0, -1.0312,
                0, -11.184 , 9.0663, -20.25 , 20.25, -20.25,
                6.9621, 0 , 12.91, 3.776 , 19.438, 6.0313,
                2.1709, 1.2419 , 4.9916, 1.2528 , 7.1562, 0,
                1.9902, -1.1517 , 3.3527,-3.6859 , 3.5625,-6.0313 ];

            var count = 9;


            // 从下到上
            if (direction == InsertDirection.Left)
            {
                for (int i = 0; i < count; i++)
                {
                    var offset = 6 * i;
                    var ia1 = offset + 0;
                    var ia2 = offset + 1;
                    var ib1 = offset + 2;
                    var ib2 = offset + 3;
                    var ic1 = offset + 4;
                    var ic2 = offset + 5;

                    var na1 = arr[ia1];
                    var na2 = arr[ia2];
                    var nb1 = arr[ib1];
                    var nb2 = arr[ib2];
                    var nc1 = arr[ic1];
                    var nc2 = arr[ic2];

                    //sb.Append($"l  {nc1} {nc2} ");
                    sb.Append($"c {na1 * scale} {na2 * scale} {nb1 * scale} {nb2 * scale} {nc1 * scale} {nc2 * scale} ");
                }
            }

            // 从下到上
            if (direction == InsertDirection.Right)
            {
                for (int i = 0; i < count; i++)
                {
                    var offset = 6 * i;
                    var ia1 = offset + 0;
                    var ia2 = offset + 1;
                    var ib1 = offset + 2;
                    var ib2 = offset + 3;
                    var ic1 = offset + 4;
                    var ic2 = offset + 5;

                    var na1 = -arr[ia1];
                    var na2 = arr[ia2];
                    var nb1 = -arr[ib1];
                    var nb2 = arr[ib2];
                    var nc1 = -arr[ic1];
                    var nc2 = arr[ic2];

                    //sb.Append($"l  {nc1} {nc2} ");
                    sb.Append($"c {na1 * scale} {na2 * scale} {nb1 * scale} {nb2 * scale} {nc1 * scale} {nc2 * scale} ");
                }
            }

            // 从右到左
            if (direction == InsertDirection.Up)
            {
                for (int i = 0; i < count; i++)
                {
                    var offset = 6 * i;
                    var ia1 = offset + 0;
                    var ia2 = offset + 1;
                    var ib1 = offset + 2;
                    var ib2 = offset + 3;
                    var ic1 = offset + 4;
                    var ic2 = offset + 5;

                    var na1 = arr[ia2];
                    var na2 = arr[ia1];
                    var nb1 = arr[ib2];
                    var nb2 = arr[ib1];
                    var nc1 = arr[ic2];
                    var nc2 = arr[ic1];

                    //sb.Append($"l  {nc1} {nc2} ");
                    sb.Append($"c {na1 * scale} {na2 * scale} {nb1 * scale} {nb2 * scale} {nc1 * scale} {nc2 * scale} ");
                }
            }

            // 从右到左
            if (direction == InsertDirection.Down)
            {
                for (int i = 0; i < count; i++)
                {
                    var offset = 6 * i;
                    var ia1 = offset + 0;
                    var ia2 = offset + 1;
                    var ib1 = offset + 2;
                    var ib2 = offset + 3;
                    var ic1 = offset + 4;
                    var ic2 = offset + 5;

                    var na1 = arr[ia2];
                    var na2 = -arr[ia1];
                    var nb1 = arr[ib2];
                    var nb2 = -arr[ib1];
                    var nc1 = arr[ic2];
                    var nc2 = -arr[ic1];

                    //sb.Append($"l  {nc1} {nc2} ");
                    sb.Append($"c {na1 * scale} {na2 * scale} {nb1 * scale} {nb2 * scale} {nc1 * scale} {nc2 * scale} ");
                }
            }
            return sb.ToString();
        }

        ///<summary>逆时针绘制。</summary>
        private static string GetCurveReverse(InsertDirection direction, double size = 100d)
        {
            // 左边的朝向。
            var unitSize = 100d;
            var scale = size / unitSize;

            var sb = new StringBuilder();

            /*
             
            M0 -40.5002
            c -0.2098 , 2.3454 , -1.5723  , 4.8796 , -3.5625, 6.0313,
            c -2.1646, 1.2528, -4.9853, 1.2419, -7.1562 , 0,
            c -6.528 ,-2.2553, -12.4759, -6.0313, -19.438, -6.0313,
            c-11.1837 ,0 ,-20.25 ,9.066 ,-20.25, 20.25,
            c 0 , 0.34945, -0.017, 0.6861, 0, 1.0312,
            c 0.542, 10.6997, 9.416, 19.219, 20.25, 19.219,
            c 6.84, 0.2364, 13.1662, -3.6103, 19.438, -6.0312,
            c 2.1708, -1.2418, 4.9916, -1.2527, 7.1562, 0,
            c 1.9902, 1.1518, 3.3527, 3.6858, 3.5625, 6.0312,
             */

            // 从下到上。
            double[] arr = [
                -0.2098 , 2.3454 , -1.5723  , 4.8796 , -3.5625, 6.0313,
                -2.1646, 1.2528, -4.9853, 1.2419, -7.1562 , 0,
                -6.528 ,-2.2553, -12.4759, -6.0313, -19.438, -6.0313,
                -11.1837 ,0 ,-20.25 ,9.066 ,-20.25, 20.25,
                0 , 0.34945, -0.017, 0.6861, 0, 1.0312,
                0.542, 10.6997, 9.416, 19.219, 20.25, 19.219,
                6.84, 0.2364, 13.1662, -3.6103, 19.438, -6.0312,
                2.1708, -1.2418, 4.9916, -1.2527, 7.1562, 0,
                1.9902, 1.1518, 3.3527, 3.6858, 3.5625, 6.0312, ];

            var count = 9;


            // 从下到上
            if (direction == InsertDirection.Left)
            {
                for (int i = 0; i < count; i++)
                {
                    var offset = 6 * i;
                    var ia1 = offset + 0;
                    var ia2 = offset + 1;
                    var ib1 = offset + 2;
                    var ib2 = offset + 3;
                    var ic1 = offset + 4;
                    var ic2 = offset + 5;

                    var na1 = arr[ia1];
                    var na2 = arr[ia2];
                    var nb1 = arr[ib1];
                    var nb2 = arr[ib2];
                    var nc1 = arr[ic1];
                    var nc2 = arr[ic2];

                    //sb.Append($"l  {nc1} {nc2} ");
                    sb.Append($"c {na1 * scale} {na2 * scale} {nb1 * scale} {nb2 * scale} {nc1 * scale} {nc2 * scale} ");
                }
            }

            // 从下到上
            if (direction == InsertDirection.Right)
            {
                for (int i = 0; i < count; i++)
                {
                    var offset = 6 * i;
                    var ia1 = offset + 0;
                    var ia2 = offset + 1;
                    var ib1 = offset + 2;
                    var ib2 = offset + 3;
                    var ic1 = offset + 4;
                    var ic2 = offset + 5;

                    var na1 = -arr[ia1];
                    var na2 = arr[ia2];
                    var nb1 = -arr[ib1];
                    var nb2 = arr[ib2];
                    var nc1 = -arr[ic1];
                    var nc2 = arr[ic2];

                    //sb.Append($"l  {nc1} {nc2} ");
                    sb.Append($"c {na1 * scale} {na2 * scale} {nb1 * scale} {nb2 * scale} {nc1 * scale} {nc2 * scale} ");
                }
            }

            // 从右到左
            if (direction == InsertDirection.Up)
            {
                for (int i = 0; i < count; i++)
                {
                    var offset = 6 * i;
                    var ia1 = offset + 0;
                    var ia2 = offset + 1;
                    var ib1 = offset + 2;
                    var ib2 = offset + 3;
                    var ic1 = offset + 4;
                    var ic2 = offset + 5;

                    var na1 = arr[ia2];
                    var na2 = arr[ia1];
                    var nb1 = arr[ib2];
                    var nb2 = arr[ib1];
                    var nc1 = arr[ic2];
                    var nc2 = arr[ic1];

                    //sb.Append($"l  {nc1} {nc2} ");
                    sb.Append($"c {na1 * scale} {na2 * scale} {nb1 * scale} {nb2 * scale} {nc1 * scale} {nc2 * scale} ");
                }
            }

            // 从右到左
            if (direction == InsertDirection.Down)
            {
                for (int i = 0; i < count; i++)
                {
                    var offset = 6 * i;
                    var ia1 = offset + 0;
                    var ia2 = offset + 1;
                    var ib1 = offset + 2;
                    var ib2 = offset + 3;
                    var ic1 = offset + 4;
                    var ic2 = offset + 5;

                    var na1 = arr[ia2];
                    var na2 = -arr[ia1];
                    var nb1 = arr[ib2];
                    var nb2 = -arr[ib1];
                    var nc1 = arr[ic2];
                    var nc2 = -arr[ic1];

                    //sb.Append($"l  {nc1} {nc2} ");
                    sb.Append($"c {na1 * scale} {na2 * scale} {nb1 * scale} {nb2 * scale} {nc1 * scale} {nc2 * scale} ");
                }
            }
            return sb.ToString();
        }

        ///<summary>创建拼图路径。</summary>
        private static string GetPath(JigsawConfig config, double size = 100)
        {
            var unitSize = 100d;
            var scale = size / unitSize;
            var sb = new StringBuilder();
            sb.Append("m 0 0");
            sb.Append($"h {size}");

            if (config.Top == HoleType.Out)
                sb.Append(GetCurve(InsertDirection.Up, size));
            else if (config.Top == HoleType.In)
                sb.Append(GetCurve(InsertDirection.Down, size));
            else if (config.Top == HoleType.Flat)
                sb.Append($"h{-40.5002 * scale}");

            sb.Append($"h {size}");
            sb.Append($"v {size}");

            if (config.Right == HoleType.Out)
                sb.Append(GetCurve(InsertDirection.Right, size));
            else if (config.Right == HoleType.In)
                sb.Append(GetCurve(InsertDirection.Left, size));
            else if (config.Right == HoleType.Flat)
                sb.Append($"v{-40.5002 * scale}");

            sb.Append($"v {size}");
            sb.Append($"h -{size}");

            if (config.Bottom == HoleType.Out)
                sb.Append(GetCurveReverse(InsertDirection.Down, size));
            else if (config.Bottom == HoleType.In)
                sb.Append(GetCurveReverse(InsertDirection.Up, size));
            else if (config.Bottom == HoleType.Flat)
                sb.Append($"h{40.5002 * scale}");

            sb.Append($"h -{size}");
            sb.Append($"v -{size}");

            if (config.Left == HoleType.Out)
                sb.Append(GetCurveReverse(InsertDirection.Left, size));
            else if (config.Left == HoleType.In)
                sb.Append(GetCurveReverse(InsertDirection.Right, size));
            else if (config.Left == HoleType.Flat)
                sb.Append($"v{40.5002 * scale}");

            sb.Append($"v -{size}");
            sb.Append("z");
            return sb.ToString();
        }

        public static StreamGeometry CreateJigsaw(JigsawConfig config, double size = 100d)
        {
            return StreamGeometry.Parse(GetPath(config, size));
        }

        public static StreamGeometry CreateJigsawWithSize(JigsawConfig config, double rectSize = 100d)
        {
            var unitRectSize = 100 + 100 - 40.5002;

            var scale = rectSize / unitRectSize;

            var unitSize = 100;
            var newUnitSize = unitRectSize * scale;

            return CreateJigsaw(config, newUnitSize);
        }
    }
}
